#ifndef NETLIB_LOGSTREAM_H
#define NETLIB_LOGSTREAM_H

// 日志IO流类，重载运算符<<将数据格式化为字符串存入缓冲区

#include "noncopyable.h"
#include "StringPiece.h"
#include "Types.h"
#include <assert.h>
#include <string.h> // memcpy

namespace netlib
{

namespace detail
{

const int kSmallBuffer = 4000;          // 默认缓冲区大小
const int kLargeBuffer = 4000*1000;     // 大型缓冲区

// SIZE非类型参数
template<int SIZE>
class FixedBuffer : noncopyable // 不可拷贝 IO缓冲区类
{
public:

    // 初始化的时候缓冲区为空，所以cur_指向首地址data_，setCookie暂无用处
    FixedBuffer() : cur_(data_) { setCookie(cookieStart); }

    ~FixedBuffer() { setCookie(cookieEnd); }

    void append(const char* buf, size_t len) // 向缓冲区输入一个字符串
    {
        // 此处未考虑到缓冲区已满的情况，未完善
        if (implicit_cast<size_t>(avail()) > len)
        {
            memcpy(cur_, buf, len);
            cur_ += len;
        }
    }

    const char* data() const { return data_; } // 返回缓冲区首地址

    // 返回缓冲区的大小
    int length() const { return static_cast<int>(cur_ - data_); }

    char* current() { return cur_; } // 返回缓冲区空闲起始地址

    // 返回缓冲区剩余容量
    int avail() const { return static_cast<int>(end() - cur_); }

    void add(size_t len) { cur_ += len; } // 空闲指针后移len个单位

    // 缓冲区清零重置
    void reset() { cur_ = data_; }

    // 初始化缓冲区
    void bzero() { memZero(data_, sizeof data_); }

    const char* debugString(); // 将缓冲区cur处加'\0'，使得缓冲区成为一个字符串

    void setCookie(void (*cookie)()) { cookie_ = cookie; } // 修改函数指针，暂无用处

    // 将缓冲区转换成string类型返回
    string toString() const { return string(data_, length()); }

    // 将缓冲区转换成StringPiece类型返回
    StringPiece toStringPiece() const { return StringPiece(data_, length()); }

private:

    // 返回缓冲区末地址的后一位
    const char* end() const { return data_ + sizeof data_; }

    static void cookieStart(); // 未实现

    static void cookieEnd(); // 未实现

    void (*cookie_)();      // 函数指针，暂未使用
    char data_[SIZE];       // 缓冲区首地址
    char* cur_;             // 缓冲区可用起始地址

}; // class FixedBuffer end

} // namespace detail end

class LogStream : noncopyable // 不可拷贝
{
    typedef LogStream self;

public:
    typedef detail::FixedBuffer<detail::kSmallBuffer> Buffer; // 缓冲区大小4000

    self& operator<<(bool v) // bool类型的输入
    {
        buffer_.append(v ? "1" : "0", 1); // 转换成字符存入缓冲区
        return *this;
    }

    self& operator<<(short);
    self& operator<<(unsigned short);
    self& operator<<(int);
    self& operator<<(unsigned int);
    self& operator<<(long);
    self& operator<<(unsigned long);
    self& operator<<(long long);
    self& operator<<(unsigned long long);
    self& operator<<(const void*);

    self& operator<<(float v)
    {
        *this << static_cast<double>(v);
        return *this;
    }
    self& operator<<(double);
    // self& operator<<(long double);

    self& operator<<(char v)
    {
        buffer_.append(&v, 1);
        return *this;
    }

    self& operator<<(const char* str)
    {
        if (str)
            buffer_.append(str, strlen(str));
        else
            buffer_.append("(null)", 6);
        return *this;
    }

    self& operator<<(const unsigned char* str)
    { return operator<<(reinterpret_cast<const char*>(str)); }

    self& operator<<(const string& v)
    {
        buffer_.append(v.c_str(), v.size());
        return *this;
    }

    self& operator<<(const StringPiece& v)
    {
        buffer_.append(v.data(), v.size());
        return *this;
    }

    self& operator<<(const Buffer& v)
    {
        *this << v.toStringPiece();
        return *this;
    }
    
    // 向缓冲区添加字符串
    void append(const char* data, int len) { buffer_.append(data, len); }

    const Buffer& buffer() const { return buffer_; } // 返回一个缓冲区对象

    void resetBuffer() { buffer_.reset(); } // 重置缓冲区

private:
    void staticCheck();

    template<typename T>
    void formatInteger(T); // 数值类型转字符串,函数模板，convert的封装

    Buffer buffer_; // IO类中包含一个缓冲区对象

    static const int kMaxNumericSize = 32; // 数值类型最多支持32位二进制数

}; // class LogStream end

class Fmt // 内嵌类，用于检查格式保证是算术类型
{
public:
    template<typename T>
    Fmt(const char* fmt, T val);

    const char* data() const { return buf_; }

    int length() const { return length_; }

private:
    char buf_[32];      // 存储数值的字符串数组
    int length_;        // 字符串长度

}; // class Fmt end

inline LogStream& operator<<(LogStream& s, const Fmt& fmt)
{
    s.append(fmt.data(), fmt.length());
    return s;
}

// Format quantity n in SI units (k, M, G, T, P, E).
// The returned string is atmost 5 characters long.
// Requires n >= 0
string formatSI(int64_t n);

// Format quantity n in IEC (binary) units (Ki, Mi, Gi, Ti, Pi, Ei).
// The returned string is atmost 6 characters long.
// Requires n >= 0
string formatIEC(int64_t n);

} // namespace netlib end

#endif